package main

import (
	"fmt"
	"reflect"
	"unsafe"
)

/*
string 源码分析

*/

func main() {
	//str := "hello world string hhhhhhhhhhhhhhhhhhhhhhhhhhh"
	//1.首先不管你定义的字符串变量的内容有多长他都只占16个字节
	//2.golang中字符串的内容是存在常量区，他通过unsafe.pointer指针指向常量区(所以你想改变字符串的其中一个字符是无法改变的)
	//3.
	//fmt.Println(unsafe.Sizeof(str))

	/*
			字符串常量区规则：
			字符串常量区是只读
			对多个相同内容的字符串
			比如：
			str1:="hello"
			str2:="hello"
		    如果直接通过fmt.Println(&str1,&str2)是看不出来的
		    需要反汇编才能，但是用C语言可以看出来
			指向同一内存地址
	*/
	str1 := "hello"
	str2 := "hello"
	//这两个字符串的内存地址肯定是不相同的（原因是：这初始化的两个字符串相当于是
	//初始化的两个stringStruct结构体，所有他们的内存地址肯定是不相同的,但是这两个
	//结构体内部的Data数据区的指针指向的内存就是同一个了）
	fmt.Println(&str1)
	fmt.Println(&str2)

	x1 := (*reflect.StringHeader)(unsafe.Pointer(&str1))
	x2 := (*reflect.StringHeader)(unsafe.Pointer(&str2))
	// 底层都是指向相同的 []byte
	fmt.Printf("data add: %#v, %#v\n", x1.Data, x2.Data)

	/*
		硬编码常量
	 	fmt.Println("hello") //此时“hello”就是硬编码
	*/
}
